package main

import (
	"log"
	"reflect"

	console "github.com/asynkron/goconsole"
	"github.com/asynkron/protoactor-go/actor"
	"github.com/asynkron/protoactor-go/remote"
	"google.golang.org/protobuf/proto"

	"learn-go/protoactor-go/remote-benchmark/messages"
)

type echoActor struct {
	sender   *actor.PID
	handlers map[reflect.Type]func(context actor.Context)
}

func (state *echoActor) Receive(context actor.Context) {
	switch msg := context.Message().(type) {
	case proto.Message:
		if handler, ok := state.handlers[reflect.TypeOf(msg)]; ok {
			handler(context)
		}
		//case *messages.StartRemote:
		//	log.Printf("Starting for %s", msg.Sender)
		//	state.sender = msg.Sender
		//	context.Respond(&messages.Start{})
		//case *messages.Ping:
		//	context.Send(state.sender, &messages.Pong{})
	}
}

func main() {
	// runtime.GOMAXPROCS(runtime.NumCPU() * 1)
	// runtime.GC()

	props := actor.
		PropsFromProducer(func() actor.Actor {
			state := &echoActor{
				handlers: map[reflect.Type]func(context actor.Context){},
			}

			state.handlers[reflect.TypeOf((*messages.StartRemote)(nil))] = func(context actor.Context) {
				msg := context.Message().(*messages.StartRemote)
				log.Printf("Starting for %s", msg.Sender)
				state.sender = msg.Sender
				context.Respond(&messages.Start{})
			}

			state.handlers[reflect.TypeOf((*messages.Ping)(nil))] = func(context actor.Context) {
				context.Send(state.sender, &messages.Pong{})
			}

			return state
		},
			actor.WithMailbox(actor.Bounded(1000000)))

	system := actor.NewActorSystem()
	r := remote.NewRemote(system, remote.Configure("127.0.0.1", 12000 /*, remote.WithCallOptions(grpc.UseCompressor(gzip.Name))*/))
	r.Register("echo", props)
	r.Start()

	rootContext := system.Root

	rootContext.SpawnNamed(props, "remote")

	console.ReadLine()
	r.Shutdown(true)
}
